
#ifndef _REACTOR_INTERRUPTER_H
#define _REACTOR_INTERRUPTER_H
#include "SockOps.h"

namespace NetIO
{

class Reactor_Interrupter
{
public:
	// Constructor.
	Reactor_Interrupter( )
	{
		EventHandle handle = socket(
		                         AF_INET, SOCK_STREAM, 0 );
		int opt = 1;
		setsockopt( handle,
		            SOL_SOCKET, SO_REUSEADDR, ( char* ) &opt, sizeof( opt ) );

		sockaddr_in addr;
		socklen_t addr_len = sizeof( addr );
		memset( &addr, 0, sizeof( addr ) );
		addr.sin_family = AF_INET;
		addr.sin_addr.s_addr = inet_addr( "127.0.0.1" );
		addr.sin_port = 0;
		bind( handle, ( const sockaddr* ) &addr, addr_len );
		listen( handle,5 );

		getsockname( handle, ( sockaddr* ) &addr,&addr_len );

		read_handle_ = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
		connect( read_handle_, ( const sockaddr* ) &addr,addr_len );

		write_handle_ = accept( handle, ( sockaddr* ) &addr, &addr_len );

		SockOps::set_non_blocking( read_handle_ );

		opt = 1;
		setsockopt( read_handle_,
		            IPPROTO_TCP, TCP_NODELAY, ( char* ) &opt, sizeof( opt ) );

		SockOps::set_non_blocking( write_handle_ );

		opt = 1;
		setsockopt( write_handle_,
		            IPPROTO_TCP, TCP_NODELAY, ( char* ) &opt, sizeof( opt ) );
		SockOps::close_socket( handle );
	}

	~Reactor_Interrupter( )
	{
		SockOps::close_socket( read_handle_ );
		SockOps::close_socket( write_handle_ );
	}

	void interrupt( )
	{
		char byte = 0;
		send( write_handle_, &byte, 1, 0 );
	}
	EventHandle read_handle( )
	{
		return read_handle_;
	}
	bool reset( )
	{
		char data;
		int bytes_read = 1;

		while( bytes_read > 0 )
			bytes_read = recv( read_handle_, &data, 1, 0 );

		return true;
	}

private:
	EventHandle read_handle_;

	EventHandle write_handle_;
};

};

#endif
